﻿/*              Copyright(c) 2008 Dave Sexton              *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace DaveSexton.DocToMaml
{
	internal sealed class FolderInput : InputBase
	{
		#region Public Properties
		public override ICollection<Exception> ConversionErrors
		{
			get
			{
				return conversionErrors.AsReadOnly();
			}
		}

		public string ResultFolder { get; private set; }

		public override string ConceptualArtFileXml
		{
			get
			{
				if (ResultFolder != null && (conceptualArtFileXml == null || conceptualArtFileXmlDirty))
					CreateConceptualArtFileXml();

				return conceptualArtFileXml;
			}
		}

		public int UniqueImageCount
		{
			get
			{
				return Images.GetImageCountForInputs(FileInputsAsInterfaces);
			}
		}

		public override IEnumerable<string> Files
		{
			get
			{
				if (files.Count == 0 || filesDirty)
				{
					files.Clear();
					files.AddRange(System.IO.Directory.GetFiles(FullPath, "*.htm", System.IO.SearchOption.TopDirectoryOnly));
				}

				return files.AsReadOnly();
			}
		}

		public override ICollection<IInput> Subinputs
		{
			get
			{
				return new List<IInput>(FileInputsAsInterfaces).AsReadOnly();
			}
		}
		#endregion

		#region Private / Protected
		private IEnumerable<IInput> FileInputsAsInterfaces
		{
			get
			{
				foreach (IInput input in inputs)
					yield return input;
			}
		}

		private readonly List<string> files = new List<string>();
		private readonly List<FileInput> inputs = new List<FileInput>();
		private readonly List<Exception> conversionErrors = new List<Exception>();
		private readonly System.IO.FileSystemWatcher watcher;
		private string conceptualArtFileXml;
		private bool conceptualArtFileXmlDirty, filesDirty;
		private int processedImageCount, processedLinkCount;
		private TimeSpan conversionTime;
		private DateTime conversionStart;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="FileInput" /> class.
		/// </summary>
		public FolderInput(string path, ConceptualImageManager imageManager, FileGuidManager guidManager)
			: base(path, imageManager, guidManager)
		{
			watcher = new System.IO.FileSystemWatcher(path, "*.htm");
			watcher.IncludeSubdirectories = false;
			watcher.NotifyFilter = System.IO.NotifyFilters.CreationTime | System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.FileName;
			watcher.Renamed += (o, e) => filesDirty = true;
			watcher.Created += (o, e) => filesDirty = true;
			watcher.Changed += (o, e) => filesDirty = true;
			watcher.Deleted += (o, e) => filesDirty = true;
			watcher.EnableRaisingEvents = true;
		}
		#endregion

		#region Methods
		public override int Convert(string targetFolder)
		{
			processedImageCount = 0;
			processedLinkCount = 0;
			conversionErrors.Clear();

			ResultFolder = targetFolder;

			int count = 0;

			conversionStart = DateTime.Now;

			foreach (string file in Files)
			{
				try
				{
					FileInput input = new FileInput(file, Images, Guids);
					input.Rules.DefaultRules = Rules;

					count += input.Convert(targetFolder);
					processedImageCount += input.ProcessedImageCount;
					processedLinkCount += input.ProcessedLinkCount;

					inputs.Add(input);
				}
				catch (HtmlToMamlConversionException ex)
				{
					conversionErrors.Add(ex);
				}
			}

			conversionTime = DateTime.Now - conversionStart;

			conceptualArtFileXmlDirty = true;

			if (conversionErrors.Count > 0)
				throw conversionErrors[conversionErrors.Count - 1];

			return count;
		}

		private void CreateConceptualArtFileXml()
		{
			conceptualArtFileXml = Images.CreateConceptualArtFileXml(FileInputsAsInterfaces);
			conceptualArtFileXmlDirty = false;
		}

		protected override void WriteLogStart(System.IO.TextWriter writer)
		{
			writer.WriteLine("Folder: {0}", FullPath);

			if (ResultFolder == null)
			{
				writer.WriteLine();
				writer.WriteLine(Resources.Text.NotConverted);
			}
			else
			{
				writer.WriteLine("Output: {0}", ResultFolder);
				writer.WriteLine("# files: {0}", inputs.Count);
			}
		}

		protected override void WriteLogContents(System.IO.TextWriter writer)
		{
			base.WriteLogContents(writer);

			if (ResultFolder != null)
			{
				writer.WriteLine("Conversion start time: {0:T}", conversionStart);
				writer.WriteLine("Conversion total time: {0}", conversionTime);
				writer.WriteLine();
				writer.WriteLine("# images: {0}", processedImageCount);
				writer.WriteLine("# unique images: {0}", UniqueImageCount);
				writer.WriteLine("# links: {0}", processedLinkCount);
				writer.WriteLine();
				writer.WriteLine("File logs:");
				writer.WriteLine();

				foreach (FileInput input in inputs)
				{
					input.WriteLog(writer);
					writer.WriteLine();
				}
			}
		}

		protected override void Dispose(bool disposing)
		{
			if (disposing)
				watcher.Dispose();

			base.Dispose(disposing);
		}
		#endregion
	}
}
